
function createTask01Alphabet(n) {
    if (typeof(n) !== 'number') {
        alert("Alphabet length should be a number");
        return;
    }
    if (n < 2 || n > 35) {
        alert("Alphabet length is expected to be greater than 1 and less than 36");
        return;
    }
    var symbols = "01234567890abcdefghijklmnopqrstuvwxyz";
    var alphabetChars = new Array();
    for (var i = 0; i < n; ++i) {
        alphabetChars.push(symbols.charAt(i));
    }
    return new Alphabet(alphabetChars, symbols.charAt(0));
};

function createTask01FilledSequenceTape(n, alphabet) {
    var tape = new Tape(alphabet);
    var fillSymbol = alphabet.getSymbols()[1];
    for (var i = 0; i < n; ++i) {
        tape.setSymbol(i, fillSymbol);
    }
    return tape;
};

function getTask01RandomInputLength() {
    return Math.floor(Math.random()*3 + 1);
};

/**
 * Creates an object of class Task, which represents a task of n copying symbols of 2-character alphabet.
 * Ex. for input 0...01110...0 the output is 0...01111110...0
 */
function createTask01() {
    var alphabet = createTask01Alphabet(2);
    var inputLength = getTask01RandomInputLength();
    var inputTape = createTask01FilledSequenceTape(inputLength, alphabet);
    var outputTape = createTask01FilledSequenceTape(2 * inputLength, alphabet);
    var taskText = "The task is to build a Turing Machine that would copy it's input. Ex. for input 0...01110...0 the output is 0...01111110...0";
    return new Task(inputTape, outputTape, taskText);
};

function createTask01EraseInputState(alphabet) {
    var zero = alphabet.getSymbols()[0];
    var one = alphabet.getSymbols()[1];
    var rule0 = new Rule(Rule.MoveType.RIGHT, zero, "Halt");
    var rule1 = new Rule(Rule.MoveType.RIGHT, zero, "Skip input");
    var state = new State("Erase input");
    state.addRule(zero, rule0);
    state.addRule(one, rule1);
    return state;
};

function createTask01SkipInputState(alphabet) {
    var zero = alphabet.getSymbols()[0];
    var one = alphabet.getSymbols()[1];
    var rule0 = new Rule(Rule.MoveType.RIGHT, zero, "Skip output");
    var rule1 = new Rule(Rule.MoveType.RIGHT, one, "Skip input");
    var state = new State("Skip input");
    state.addRule(zero, rule0);
    state.addRule(one, rule1);
    return state;
};

function createTask01SkipOutputState(alphabet) {
    var zero = alphabet.getSymbols()[0];
    var one = alphabet.getSymbols()[1];
    var rule0 = new Rule(Rule.MoveType.RIGHT, one, "Write one");
    var rule1 = new Rule(Rule.MoveType.RIGHT, one, "Skip output");
    var state = new State("Skip output");
    state.addRule(zero, rule0);
    state.addRule(one, rule1);
    return state;
};

function createTask01WriteOneState(alphabet) {
    var zero = alphabet.getSymbols()[0];
    var one = alphabet.getSymbols()[1];
    var rule0 = new Rule(Rule.MoveType.LEFT, one, "Go back(skip output)");
    var rule1 = new Rule(Rule.MoveType.LEFT, one, "Go back(skip output)");
    var state = new State("Write one");
    state.addRule(zero, rule0);
    state.addRule(one, rule1);
    return state;
};

function createTask01GoBackSkipOutputState(alphabet) {
    var zero = alphabet.getSymbols()[0];
    var one = alphabet.getSymbols()[1];
    var rule0 = new Rule(Rule.MoveType.LEFT, zero, "Go back(skip input)");
    var rule1 = new Rule(Rule.MoveType.LEFT, one, "Go back(skip output)");
    var state = new State("Go back(skip output)");
    state.addRule(zero, rule0);
    state.addRule(one, rule1);
    return state;
};

function createTask01GoBackSkipInputState(alphabet) {
    var zero = alphabet.getSymbols()[0];
    var one = alphabet.getSymbols()[1];
    var rule0 = new Rule(Rule.MoveType.RIGHT, zero, "Erase input");
    var rule1 = new Rule(Rule.MoveType.LEFT, one, "Go back(skip input)");
    var state = new State("Go back(skip input)");
    state.addRule(zero, rule0);
    state.addRule(one, rule1);
    return state;
};

function createTask01HaltState() {
    return new State("Halt");
};

/**
 * Creates an object of class RulesTable that is a solution to passed task01.
 */
function createTask01Solution(task) {
    var alphabet = task.getInputTape().getAlphabet();
    var eraseInput = createTask01EraseInputState(alphabet);
    var skipInput = createTask01SkipInputState(alphabet);
    var skipOutput = createTask01SkipOutputState(alphabet);
    var writeOne = createTask01WriteOneState(alphabet);
    var goBackSkipOutput = createTask01GoBackSkipOutputState(alphabet);
    var goBackSkipInput = createTask01GoBackSkipInputState(alphabet);
    var halt = createTask01HaltState();
    var states = new Array(eraseInput, skipInput, skipOutput, writeOne, goBackSkipOutput, goBackSkipInput, halt);
    return new RulesTable(states);
};